package pl.poznan.put.cs.idss.students.coolring.ui.components;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import javax.swing.ImageIcon;
import javax.swing.JPanel;

import pl.poznan.put.cs.idss.students.coolring.properties.Properties;
import pl.poznan.put.cs.idss.students.coolring.ui.GeneralWindow;

public class MainCanvas extends JPanel implements MouseMotionListener {

	private static final long serialVersionUID = -802113887678218545L;

	private int width;
	private int height;

	private int canvasWidth;
	private int canvasHeight;

	private int imageWidth = 0;
	private int imageHeight = 0;

	private int imageStartX = 0;
	private int imageStartY = 0;

	private int toolBoxWidth = Properties.number("toolbox_width");
	private int canvasMargin = Properties.number("canvas_margin");

	Logger log = Logger.getLogger("pl.poznan.put.cs.idss.students.coolring");

	private Image image = null;
	private ImageIcon imageHelper = null;
	private Image imageMock = null;

	private int lastScribleLength = 0;

	private GeneralWindow parent;

	private List<ColoredPoint> pointsList = new ArrayList<ColoredPoint>();
	private List<Integer> undoSizes = new ArrayList<Integer>();

	public MainCanvas(GeneralWindow parent) {

		this.parent = parent;

		width = Properties.number("image_width");
		height = Properties.number("image_height");

		canvasWidth = Properties.number("canvas_width");
		canvasHeight = Properties.number("canvas_height");

		imageMock = Toolkit.getDefaultToolkit().getImage(
				MainCanvas.class.getResource(Properties.get("image_mock")));

		addMouseMotionListener(this);

		setSize(width, height);
		setVisible(true);

	}

	public void drawImage(String path) throws Exception {

		Image img = null;

		try {
			log.info("Trying to open image: " + path);
			img = Toolkit.getDefaultToolkit().getImage(path);

			if (img == null) {
				log.severe("Image does not exist or is invalid");
				return;
			} else {
				setImage(img);
				imageHelper = new ImageIcon(getImage());
				if (imageHelper.getIconWidth() < 0) {
					throw new Exception("Not an image");
				}
				scaleImage();
			}

			if (isValid()) {
				repaint();
			} else {
				log.severe("Canvas is not valid - cannot draw");
			}
		} catch (Exception e) {
			log.severe("Cannot open: " + path);
			throw new Exception("Cannot draw");
		}

	}

	private void scaleImage() {
		if (imageHelper.getIconWidth() <= width
				&& imageHelper.getIconHeight() <= height) {
			imageWidth = imageHelper.getIconWidth();
			imageHeight = imageHelper.getIconHeight();
		} else {
			if (imageHelper.getIconWidth() > imageHelper.getIconHeight()) {
				imageWidth = width;
				imageHeight = width * imageHelper.getIconHeight()
						/ imageHelper.getIconWidth();
			} else {
				imageHeight = height;
				imageWidth = height * imageHelper.getIconWidth()
						/ imageHelper.getIconHeight();
			}
		}
	}

	public void paint(Graphics g) {
		g.clearRect(toolBoxWidth, 0, canvasWidth, canvasHeight);
		g.setColor(Color.WHITE);
		g.fillRect(toolBoxWidth, 0, canvasWidth, canvasHeight);
		if (getImage() != null) {
			imageStartX = Math.abs(width - imageWidth) / 2;
			imageStartY = Math.abs(height - imageHeight) / 2;
			g.drawImage(getImage(), toolBoxWidth + canvasMargin + imageStartX,
					canvasMargin + imageStartY, imageWidth, imageHeight, this);
			g.setColor(new Color(190, 190, 190));
			g.drawRect(toolBoxWidth + canvasMargin + imageStartX, canvasMargin
					+ imageStartY, imageWidth, imageHeight);
		} else {
			g.drawImage(imageMock, toolBoxWidth + canvasMargin, canvasMargin,
					this);
		}
		for (ColoredPoint point : getPointsList()) {
			g.setColor(point.getColor());
			g.fillRect(point.getX() - 1 + 68, point.getY() + 20 - 1, 3, 3);
		}
		g.setColor(new Color(160, 160, 160));
	}

	private void addPoint(int x, int y, Color c) {
		getPointsList().add(new ColoredPoint(x, y, c));
	}

	public void undo() {
		for (int i = 0; i < undoSizes.get(undoSizes.size() - 1); i++) {
			if (getPointsList().size() > 0) {
				getPointsList().remove(getPointsList().size() - 1);
				repaint();
			}
		}
		undoSizes.remove(undoSizes.size() - 1);
	}

	public Image getImage() {
		return image;
	}

	public void setImage(Image image) {
		this.image = image;
	}

	public List<ColoredPoint> getPointsList() {
		return pointsList;
	}

	public void setPointsList(List<ColoredPoint> pointsList) {
		this.pointsList = pointsList;
	}

	public void mouseDragged(MouseEvent e) {
		if (getImage() != null) {
			addPoint(e.getX() - toolBoxWidth - canvasMargin, e.getY()
					- canvasMargin, parent.getColorPicker().getCurrentColor());
			addPoint(e.getX() - 2 - toolBoxWidth - canvasMargin, e.getY()
					- canvasMargin, parent.getColorPicker().getCurrentColor());
			addPoint(e.getX() + 2 - toolBoxWidth - canvasMargin, e.getY()
					- canvasMargin, parent.getColorPicker().getCurrentColor());
			addPoint(e.getX() - toolBoxWidth - canvasMargin, e.getY() - 2
					- canvasMargin, parent.getColorPicker().getCurrentColor());
			addPoint(e.getX() - toolBoxWidth - canvasMargin, e.getY() + 2
					- canvasMargin, parent.getColorPicker().getCurrentColor());
			lastScribleLength += 5;
			repaint();
		}
	}

	public void mouseMoved(MouseEvent e) {
		if(lastScribleLength > 0) {
			undoSizes.add(lastScribleLength);
			lastScribleLength = 0;
		}
	}

}
